package com.fjeld.middleware.util.collection;

/**
 * Created by IntelliJ IDEA.
 * User: fjeld
 * Date: 11/12/2011
 * Time: 20:04
 *
 * A map which notifies when items are added and removed
 */

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.Map.Entry;

public class ObservableHashMap<K, V> extends Observable implements Observer, Map<K, V>
{
    protected final Map<K, V> hashMap;

    public ObservableHashMap()
    {
        hashMap = new HashMap<K, V>();
    }

    public ObservableHashMap(int i)
    {
        hashMap = new HashMap<K, V>(i);
    }

    public V put(K key, V value)
    {
        if (value == null)
        {
            return null;
        }
        V result = hashMap.put(key, value);
        setChangedAndNotifyObservers(result);
        return result;
    }

    public V get(Object key)
    {
        return hashMap.get(key);
    }

    public V getAt(int position)
    {
        int index = 0;
        for (Map.Entry<K, V> entry : hashMap.entrySet())
        {
            if (index == position)
            {
                return entry.getValue();
            }
            index++;
        }
        return null;
    }

    public Collection<V> values()
    {
        return hashMap.values();
    }

    public V remove(Object key)
    {
        V result = hashMap.remove(key);
        setChangedAndNotifyObservers(result);
        return result;
    }

    public void putAll(Map<? extends K, ? extends V> map)
    {
        hashMap.putAll(map);
        setChangedAndNotifyObservers(map);
    }

    public void clear()
    {
        hashMap.clear();
        setChangedAndNotifyObservers(hashMap);
    }

    public Set<K> keySet()
    {
        return hashMap.keySet();
    }

    public boolean isEmpty()
    {
        return hashMap.isEmpty();
    }

    public boolean containsKey(Object key)
    {
        return hashMap.containsKey(key);
    }

    public boolean containsValue(Object o)
    {
        return hashMap.containsValue(o);
    }

    public Set<Entry<K, V>> entrySet()
    {
        return hashMap.entrySet();
    }

    public int size()
    {
        return hashMap.size();
    }

    private void setChangedAndNotifyObservers(Object data)
    {
        super.setChanged();
        super.notifyObservers(data);
    }

    public void update(Observable observable, Object data)
    {
        this.setChangedAndNotifyObservers(data);
    }
}